#include "test.h"

#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <fstream>
#include <iostream>
#include <string.h>
#include <set>
#include <time.h>


#include "ui/LaserFinder.h"
#include "ui/Calibrator.h"
#include "io/HMMBuilder.h"
#include "io/BaseSaver.h"
#include "io/BaseLoader.h"
#include "model/HMM.h"
#include "model/MappedRecognizer.impl.h"

#include "parsing/CommandLineParser.h"

#include "dispatcher/LaserDispatcher.h"
#include "Learner.h"
#include "RecognitionTester.h"

#include "common.h"

int test(string fileName) {
	FILE * pFile;
	pFile = fopen (fileName.c_str() , "r");
	if (pFile == NULL) {
		std::cout << "Unable to load file " << fileName << "\n";
		return 1;
	}
	
	char line [256];
	line[0] = 0;
	
	std::map<string, unsigned> successMap;
	std::map<string, unsigned> countMap;
	
	while (fgets (line, 256, pFile) != NULL) {
		puts (line);
		
		if (strlen(line) < 3) {
			continue;
		}
		
		CommandLineParser parser;
		parser.parse(line);
		
		std::map<string, string>& optmap = parser.getMap();
		std::set<string>& options = parser.getOptions();
		std::vector<string>& args = parser.getArguments();
		
		if (args.size() < 1) {
			cout << "too few arguments... skip test";
			continue;
		}
		
		string action = args[0];
		
		// get source
		const char* source = NULL;
		source = optmap[string("source")].c_str();
		if (strlen(source) == 0) {
			source = NULL;
		} else {
			if (!fileExists(source)){
				printf("Source does not exist!... skip test\n\n");
				continue;
			}
		}
		
		
		// get conf file
		const char* conf = NULL;
		conf = optmap[string("conf")].c_str();
		
		// get  camera id
		string s = optmap[string("camid")];
		int cam_id = 0;
		if (strlen(s.c_str()) != 0) {
			cam_id = atoi(s.c_str());
		}
		
		string resX = optmap[string("sizex")];
		int res_x = 640;
		if (strlen(resX.c_str()) != 0) {
			res_x = atoi(resX.c_str());
		}

		string resY = optmap[string("sizey")];
		int res_y = 480;
		if (strlen(resY.c_str()) != 0) {
			res_y = atoi(resY.c_str());
		}

		// get base directory
		string baseDir = optmap[string("base")];
		if (baseDir.length() == 0) {
			baseDir = DEFAULT_BASE_DIR;
		} else if (baseDir[baseDir.length() - 1] != '/') {
			baseDir += '/';
		}
		printf("source = %s\n\n", source);
		printf("action = %s\n\n", action.c_str());
		
		// perform actions
		if (action == string("calibrate")) {
			if (strlen(conf) == 0) {
				conf = DEFAULT_CONFIG_FILE;
				if (!fileExists(conf)) {
					printf("Default config file does not exist!... exit\n\n");
					return 1;
				}
			}
			printf("conf = %s\n\n", conf);
		
			bool manual = false;
			if (options.find("manual") != options.end()) {
				manual = true;
				printf("manual calibration...\n");
			} else {
				printf("auto calibration...\n");
			}
			//Calibrator(const char* videoStream, char* configFileName, bool manual);
			Calibrator calibr(source, conf, manual, cam_id);
		} else {
			if (strlen(conf) == 0 || !fileExists(conf)) {
				conf = DEFAULT_CONFIG_FILE;
				if (!fileExists(conf)) {
					printf("Default config file does not exist!... exit\n\n");
					return 1;
				}
			}	
			printf("conf = %s\n\n", conf);
				
			if (action == string("learn")) {
				printf("learning...\n");
				LaserFinder lf(source, conf, cam_id, res_x, res_y);
				LaserDispatcher disp(&lf);
				Learner learner(baseDir, args[1]);
				disp.addListener(&learner);
				disp.start();
				
			} else if (action == string("recognize")) {
				if (args.size() >= 2) {
					printf("recognition...\n");
					
					LaserFinder lf(source, conf, cam_id, res_x, res_y);
					LaserDispatcher disp(&lf);
					
					RecognitionTester recTester(baseDir);
					
					disp.addListener(&recTester);
					disp.start();
					
					const vector<string>& results = recTester.getResults();
					
					// verify results
					unsigned success = 0;
					for (size_t i = 0; i < results.size(); i++) {
						if(results[i] == args[1]) {
							success++;
						}
					}
					successMap[args[1]] = success;
					countMap[args[1]] = results.size();
				} else {
					cout << "roo few arguments... skip test\n\n";
				}
			} else {
				cout << "unknown command: " << line << "\nskip test\n\n";
				continue;
			}
		}
	}
		
	if (countMap.size() > 0) {
		std::ofstream fout;
		fout.open("log", fstream::app);
		if (!fout) {
			std::cout << "Unable to write log";
		}
		time_t rawtime;
		time(&rawtime);
		fout << ctime(&rawtime);
		
		std::map<string, unsigned>::iterator it;
		unsigned success = 0;
		unsigned count = 0;
		cout << "\n\nSUCCESS RATES\n\n";
		fout << "SUCCESS RATES\n\n";
		for(it = countMap.begin(); it != countMap.end(); it++) {
			string symbol = it->first;
			cout << "symbol: " << symbol << "\t" << double(successMap[symbol]) / double(countMap[symbol]) << "\n";
			fout << "symbol: " << symbol << "\t" << double(successMap[symbol]) / double(countMap[symbol]) << "\n";
			success += successMap[symbol];
			count += countMap[symbol];
		}
		cout << "TOTAL SUCCESS RATE: " << double(success) / double(count) << "\n\n";
		fout << "TOTAL SUCCESS RATE: " << double(success) / double(count) << "\n\n";
		
		fout.close();
	}
	fclose (pFile);
	return 0;
}
